package se.robertfoss.ChanImageBrowser;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.ArrayList;

import se.robertfoss.ChanImageBrowser.Fetcher.FetcherManager;
import se.robertfoss.ChanImageBrowser.Fetcher.ImageFetcher;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.gesture.Prediction;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ProgressBar;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;

public class Viewer extends Activity implements OnGesturePerformedListener {

	public static final File tempDir = new File(Environment.getExternalStorageDirectory(), "/4Chan/temp/");
	public static final File baseDir = new File(Environment.getExternalStorageDirectory(), "/4Chan/");
	
	public static final int NBR_IMAGES_TO_DOWNLOAD_DIRECTLY = 36;
	
	public static final int COLS_IN_LANDSCAPE_MODE = 3;
	public static final int COLS_IN_PORTRAIT_MODE = 2;

	private static final String SEED_URL = "http://img.4chan.org/b/imgboard.html";
	private static final String PAGE_REGEX = "\\<a href=\\\"res/([0-9]){1,20}";
	private static final int PAGE_REGEX_TRUNCATE_TO_INDEX = 13; //How many chars. of the regexp that should be removed from the matching line
	private static final String PREPEND_TO_RELATIVE_PAGE_URL = "http://boards.4chan.org/b/res/";
	private static final String IMAGE_REGEX = "//i.4cdn.org/b/src/([0-9])*.(jpg|png)";
	private static final int IMAGE_REGEX_TRUNCATE_TO_INDEX = 19; //How many chars. of the regexp that should be removed from the matching line
	private static final String PREPEND_TO_RELATIVE_IMAGE_URL = "http://i.4cdn.org/b/src/";
	
	// Parse images from reddit.com/pics
//	 private static final String SEED_URL = "http://www.reddit.com/r/pics/";
//	 private static final String IMAGE_REGEX = "http://imgur.com/([A-Za-z0-9]*.jpg|png)";
//	 private static final String PREPEND_TO_RELATIVE_IMAGE_URL = "http://imgur.com/";
//	 private static final String PAGE_REGEX = "http://www.reddit.com/r/(\\S+)\"";
//	 private static final String PREPEND_TO_RELATIVE_PAGE_URL = "http://www.reddit.com/r/";
	
	private GestureLibrary gestureLib;
	private GridView gridView;
	private ImageAdapter imageAdapter;
	private FetcherManager man;
	private ProgressBarHandler progressHandler;
	private ImageHandler imageHandler;
	

	@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		/* Set up gesture overlay */
	    GestureOverlayView gestureOverlayView = new GestureOverlayView(this);
	    View inflate = getLayoutInflater().inflate(R.layout.main, null);
	    gestureOverlayView.addView(inflate);
	    gestureOverlayView.addOnGesturePerformedListener(this);
	    gestureOverlayView.setGestureColor(Color.TRANSPARENT);
	    gestureOverlayView.setUncertainGestureColor(Color.TRANSPARENT);
	    gestureLib = GestureLibraries.fromRawResource(this, R.raw.gestures);
	    if (!gestureLib.load()) {
	      finish();
	    }
	    setContentView(gestureOverlayView);
	    
	    Log.d("Viewer", "onCreate()");

		/* Format gridview columns and rows. Support both APIs before and after 13  */
		int width;
		int height;
		Point size = new Point();
		WindowManager w = getWindowManager();
		if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2)
		{
		     w.getDefaultDisplay().getSize(size);
		     width = size.x;
		     height = size.y; 
		} else {
		     Display d = w.getDefaultDisplay(); 
		     width = d.getWidth(); 
		     height = d.getHeight(); 
		}

		gridView = (GridView) findViewById(R.id.gridview);

		int nbrCols = COLS_IN_PORTRAIT_MODE;
		/* If landscape mode */
		if (width > height) {
			nbrCols = COLS_IN_LANDSCAPE_MODE;
		}
		float thumbRelSpace = (float)8 / (float)(nbrCols*10);
		float hSpacingRelSpace = (1 - nbrCols*thumbRelSpace) / nbrCols;
		int thumbWidth = (int)((float)width * thumbRelSpace );
		int thumbHeight = (int)((float)thumbWidth * ( (float)4 / (float)3 ) );
		int hSpacing = (int)((float)width * hSpacingRelSpace);
		int vSpacing = (int)((float)height * ((float)1/(float)20));
		gridView.setColumnWidth(thumbWidth);
		gridView.setHorizontalSpacing(hSpacing);
		gridView.setVerticalSpacing(vSpacing);
		
		imageAdapter = new ImageAdapter(this, NBR_IMAGES_TO_DOWNLOAD_DIRECTLY, thumbWidth, thumbHeight);
		gridView.setAdapter(imageAdapter);
		imageHandler = new ImageHandler(imageAdapter);

//		if (savedInstanceState != null) {
//			  Parcelable state = savedInstanceState.getParcelable("gridView");
//			  if (state != null) {
//			    gridView.onRestoreInstanceState(state);
//			    printDebug("onCreate() gridView state restored");                
//			  }
//		}

		gridView.setOnItemLongClickListener(new OnItemLongClickListener() {

			public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int position, long id) {
				Log.d("Viewer", "Image " +  position + " was long-clicked!");
				Log.d("Viewer", "Trying to open file: " + Uri.parse("file:/"+ (File) imageAdapter.getItem(position)));
				imageDialog((File) imageAdapter.getItem(position));
				return false;
			}
			
		});
		
		gridView.setOnItemClickListener(new OnItemClickListener() {

			public void onItemClick(AdapterView<?> arg0, View arg1, int position, long id) {
				Log.d("Viewer", "Image " + position + " was clicked!");
				
				File file = (File) imageAdapter.getItem(position);
				Log.d("Viewer", "Expanding image: " +  file.getAbsoluteFile());
				Intent i = new Intent(Viewer.this, ExpandImage.class);
				i.putExtra("fileURI", file.getAbsoluteFile().toString());
				
				Viewer.this.startActivity(i);
			}
		});

		Log.d("Viewer", "Initializing manager thread");
		man = new FetcherManager(imageHandler, NBR_IMAGES_TO_DOWNLOAD_DIRECTLY,
				SEED_URL, PAGE_REGEX, PAGE_REGEX_TRUNCATE_TO_INDEX,
				PREPEND_TO_RELATIVE_PAGE_URL, IMAGE_REGEX, 
				IMAGE_REGEX_TRUNCATE_TO_INDEX, PREPEND_TO_RELATIVE_IMAGE_URL);

		Log.d("Viewer", "Running manager thread");
		man = (FetcherManager) man.execute();
		
		firstRunDialog();
		setupProgressBar((ProgressBar) findViewById(R.id.progress));
	}

	public void setCurrentView(View view) {
		Viewer.this.setContentView(view);
	}

	
	@Override
	protected void onResume() {	
		super.onResume();
		Log.d("Viewer", "onResume()");
		man.setFetchersPause(false);
	}
	
	@Override
	protected void onRestart() {	
		super.onRestart();
		Log.d("Viewer", "onRestart()");
	}

	@Override
	protected void onPause() {
		super.onPause();
		Log.d("Viewer", "onPause()");
		man.setFetchersPause(true);
	}

	@Override
	public void onLowMemory(){
		super.onLowMemory();
		Log.d("Viewer", "onLowMemory()");
		Toast.makeText(this, "Pausing downloads due to low memory", Toast.LENGTH_SHORT).show();
		man.setFetchersPause(true);
	}
	
	@Override
	protected void onStop(){
		super.onStop();
		Log.d("Viewer", "onStop()");
		man.setFetchersPause(true);
	}
	
	@Override
	protected void onDestroy() {
		super.onDestroy();
		Log.d("Viewer", "onDestroy()");
		clearTmp();
		man.setFetchersPause(true);
		if (man != null){
			man.destroyFetchers();
		}
		man = null;
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
		Log.d("Viewer", "onConfigurationChanged()");
	}
	
	/* TODO: Implement state saving and restoration */
//	@Override
//	protected void onSaveInstanceState(Bundle outState) {
//	    super.onSaveInstanceState(outState);
//	    Parcelable state = gridView.onSaveInstanceState();
//	    outState.putParcelable("gridView", state);
//	}
	
	

	public void addCompleteImage(File file) {
		Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;

		BitmapFactory.decodeFile(file.toString(), options);

		Log.d("Viewer", "New picture addded, " + file.toString());
		imageAdapter.addItem(file);
	}

	public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
	    ArrayList<Prediction> predictions = gestureLib.recognize(gesture);
	    for (Prediction prediction : predictions) {
	      if (prediction.score > 1.0) {
	        clearImages();
	      }
	    }
	}
	
	private void clearImages(){
		imageAdapter.clearContents();
		man.downloadNewImages(NBR_IMAGES_TO_DOWNLOAD_DIRECTLY);
		man.setFetchersPause(false);
	}
	
	private void clearTmp() {
		(new Thread(new Runnable(){

			@Override
			public void run() {
				if (tempDir != null) {
					for (File f : tempDir.listFiles()) {
						if (f != null) {
							f.delete();
						}
					}
					tempDir.delete();
					if (tempDir.getParentFile() != null) {
						tempDir.getParentFile().delete();
					}
				}
			}
		})).start();
	}
	
	private void imageDialog(final File imgFile){
        final Dialog custom = new Dialog(this);
        custom.setContentView(R.layout.save_dialog);
        Button savebtn = (Button)custom.findViewById(R.id.savebtn);
        Button sendbtn = (Button)custom.findViewById(R.id.sendbtn);
        custom.setTitle("Use Image");
        
        
        savebtn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
            	File target = new File(Environment.getExternalStorageDirectory().getPath() +"/Download/" + imgFile.getName());
            	try {
				 InputStream in = new FileInputStream(imgFile);
				 OutputStream out = new FileOutputStream(target);
				
				 byte[] buf = new byte[1024];
				 int len;
				 while ((len = in.read(buf)) > 0){
					 out.write(buf, 0, len);
				 }
				 in.close();
					out.close();
				} catch (IOException e) {
	            	Toast.makeText(getApplicationContext(), "Unable to copy image!", Toast.LENGTH_LONG).show();
					e.printStackTrace();
				}
            	custom.dismiss();
            	Toast.makeText(getApplicationContext(), "Image copied to Downloads folder", Toast.LENGTH_SHORT).show();
            }

        });
        
        sendbtn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
				Intent sendIntent = new Intent(Intent.ACTION_SEND);
			    sendIntent.setType("image/*");
			    sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(imgFile));
			    sendIntent.putExtra(Intent.EXTRA_TEXT, "Image found with 4chan Image Browser");
			    startActivity(Intent.createChooser(sendIntent, "Send image with"));
                custom.dismiss();
            }
        });
        
        custom.show();
	}
	
	private void firstRunDialog() {
	    boolean firstRun = getSharedPreferences("PREFERENCE", MODE_PRIVATE).getBoolean("firstRun", true);
	    if (firstRun){
	        getSharedPreferences("PREFERENCE", MODE_PRIVATE).edit().putBoolean("firstRun", false).commit();
	        final Dialog custom = new Dialog(this);
	        custom.setContentView(R.layout.firstrun_dialog);
	        Button okbtn = (Button)custom.findViewById(R.id.okbtn);
	        custom.setTitle("How To");
	        custom.show();
	        
	        okbtn.setOnClickListener(new View.OnClickListener() {
	            public void onClick(View view) {
	                custom.dismiss();
	            }
	        });
	    }
	}
	
	private void setupProgressBar(final ProgressBar pb) {
		progressHandler = new ProgressBarHandler(pb);
		
		
		/* TODO: Implement stop method to prevent updating progress bar
		 *        while shutting down. */
		new Thread((new Runnable(){

			@Override
			public void run() {
				while (true) {
					int max = Integer.MIN_VALUE;
					boolean sameVal = false;
					if (man != null) {
						ArrayList<Integer> p = man.getImageFetcherProgress();
						for(int i : p) {
							
							/* Determine if all values are the same */
							if (!sameVal && max == Integer.MIN_VALUE) {
								sameVal = true;
							} else if (sameVal && max != i) {
								sameVal = false;
							}
								
							if (i > max) {
								max = i;
							}
						}
					}
					if (max == Integer.MIN_VALUE || (sameVal && max == ImageFetcher.IS_UNINITIATED)) {
						Message msg = progressHandler.obtainMessage();
						msg.arg1 = 1;
						msg.arg2 = pb.getMax();
						progressHandler.sendMessage(msg);
					} else if (sameVal && max == ImageFetcher.IS_PAUSED) {
						Message msg = progressHandler.obtainMessage();
						msg.arg1 = 0;
						msg.arg2 = 0;
						progressHandler.sendMessage(msg);
					} else {
						Message msg = progressHandler.obtainMessage();
						msg.arg1 = 0;
						msg.arg2 = max;
						progressHandler.sendMessage(msg);
					}
					try {
					    Thread.sleep(200);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
			
		})).start();
	}
}